<?php

namespace common\components;


use Yii;
use yii\base\Component;
use yii\caching\Cache;
use yii\db\Connection;
use yii\db\Query;
use yii\di\Instance;
use yii\web\Cookie;

class Option extends Component
{
    const CACHE_KEY = 'ycmf.option';

    /**
     * @var Connection|string
     */
    public $db = 'db';

    /**
     * @var Cache|string
     */
    public $cache = 'cache';

    /**
     * @var string
     */
    public $table = '{{%option}}';

    /**
     * @var array
     */
    protected $options;

    /**
     * @var
     */
    private static $_updatedUserSettings;

    /**
     * @inheritDoc
     */
    public function init()
    {
        parent::init();
        $this->db = Instance::ensure($this->db, Connection::className());
        $this->cache = Instance::ensure($this->cache, Cache::className());
    }

    /**
     * 获取所有选项
     *
     * @return array|mixed
     */
    public function getOptions()
    {
        if (!isset($this->options)) {
            if (($options = $this->cache->get(self::CACHE_KEY)) === false) {
                $options = array();
                $rows = (new Query())
                    ->select('*')
                    ->from($this->table)
                    ->all($this->db);
                foreach ($rows as $row) {
                    $options[$row['name']] = unserialize($row['value']);
                }
                $this->cache->set(self::CACHE_KEY, $options);
            }
            $this->options = $options;
        }
        return $this->options;
    }

    /**
     * 获取一个选项
     *
     * @param string $name
     * @param mixed $default
     * @return mixed
     */
    public function get($name, $default = null)
    {
        $options = $this->getOptions();
        return isset($options[$name]) ? $options[$name] : $default;
    }

    /**
     * 设置一个选项
     *
     * @param $name
     * @param $value
     * @param bool $deleteCache
     */
    public function set($name, $value, $deleteCache = true)
    {
        $options = $this->getOptions();

        if (array_key_exists($name, $options) && $options[$name] === $value) {
            return;
        }

        $exists = (new Query())
            ->from($this->table)
            ->where('name=:name', array(':name' => $name))
            ->exists($this->db);
        if ($exists) {
            $this->db->createCommand()
                ->update($this->table, array(
                    'value' => serialize($value)
                ), ['name' => $name])
                ->execute();
        } else {
            $this->db->createCommand()->insert($this->table, array(
                'name' => $name,
                'value' => serialize($value)
            ))->execute();
        }

        if ($deleteCache) {
            $this->deleteCache();
        }
        $this->options[$name] = $value;
    }

    /**
     * 删除一个选项
     *
     * @param $name
     */
    public function del($name)
    {
        $this->getOptions();
        $this->db->createCommand()->delete($this->table,
            ['name' => $name])->execute();
        $this->deleteCache();
        unset($this->options[$name]);
    }

    /**
     * 删除缓存
     */
    public function deleteCache()
    {
        $this->cache->delete(self::CACHE_KEY);
    }

    /**
     * 初始化当前用户设置
     */
    public function initUserSettings()
    {
        $user = Yii::$app->getUser();
        if ($user->getIsGuest()) {
            return;
        }

        $userId = $user->getId();
        $settings = $this->get('user.settings-' . $userId, '');
        if (isset($_COOKIE['ycmf-settings-' . $user->getId()])) {
            $cookie = preg_replace('/[^A-Za-z0-9=&_]/', '', $_COOKIE['ycmf-settings-' . $userId]);
            if ($cookie == $settings) {
                return;
            }

            $lastSaved = (int)$this->get('user.settings-time-' . $userId);
            $current = isset($_COOKIE['ycmf-settings-time-' . $userId])
                ? preg_replace('/[^0-9]/', '', $_COOKIE['ycmf-settings-time-' . $userId])
                : 0;

            if ($current > $lastSaved) {
                $this->set('user.settings-' . $userId, $cookie);
                $this->set('user.settings-time-' . $userId, time() - 5);
                return;
            }
        }

        $_COOKIE['ycmf-settings-' . $userId] = $settings;
        /*
        $secure = Yii::$app->getRequest()->getIsSecureConnection();
        Yii::$app->getResponse()->cookies[] = new Cookie([
            'name' => 'ycmf-settings-' . $userId,
            'value' => $settings,
            'expire' => time() + 365 * 24 * 3600,
            'path' => Yii::$app->getRequest()->baseUrl,
            'domain' => null,
            'secure' => $secure,
        ]);

        Yii::$app->getResponse()->cookies[] = new Cookie([
            'name' => 'ycmf-settings-time-' . $userId,
            'value' => time(),
            'expire' => time() + 365 * 24 * 3600,
            'path' => Yii::$app->getRequest()->baseUrl,
            'domain' => null,
            'secure' => $secure,
        ]);
        */
    }

    /**
     * 获取当前用户所有设置
     *
     * @return array
     */
    public function getAllUserSettings()
    {
        $user = Yii::$app->getUser();
        if ($user->getIsGuest()) {
            return array();
        }
        $userId = $user->getId();

        if (isset(self::$_updatedUserSettings) && is_array(self::$_updatedUserSettings)) {
            return self::$_updatedUserSettings;
        }

        $userSettings = array();

        if (isset($_COOKIE['ycmf-settings-' . $userId])) {
            $cookie = preg_replace('/[^A-Za-z0-9=&_]/', '', $_COOKIE['ycmf-settings-' . $userId]);

            if (strpos($cookie, '=')) { // '=' cannot be 1st char
                parse_str($cookie, $userSettings);
            }
        } else {
            $option = $this->get('user.settings-' . $userId);

            if ($option && is_string($option)) {
                parse_str($option, $userSettings);
            }
        }

        self::$_updatedUserSettings = $userSettings;
        return $userSettings;
    }

    /**
     * 设置当前用户所有设置
     *
     * @param array $userSettings
     * @return bool
     */
    public function setAllUserSettings($userSettings)
    {
        $user = Yii::$app->getUser();
        if ($user->getIsGuest()) {
            return false;
        }

        $userId = $user->getId();
        $settings = '';

        foreach ($userSettings as $name => $value) {
            $_name = preg_replace('/[^A-Za-z0-9_]+/', '', $name);
            $_value = preg_replace('/[^A-Za-z0-9_]+/', '', $value);

            if (!empty($_name)) {
                $settings .= $_name . '=' . $_value . '&';
            }
        }

        $settings = rtrim($settings, '&');
        parse_str($settings, self::$_updatedUserSettings);

        $this->set('user.settings-' . $userId, $settings);
        $this->set('user.settings-time-' . $userId, time());
        return true;
    }

    /**
     * 获取当前用户某个设置
     *
     * @param $name
     * @param bool $default
     * @return mixed|null
     */
    public function getUserSetting($name, $default = false)
    {
        $allUserSettings = $this->getAllUserSettings();
        return isset($allUserSettings[$name]) ? $allUserSettings[$name] : $default;
    }

    /**
     * 设置当前用户某个设置
     *
     * @param $name
     * @param $value
     */
    public function setUserSetting($name, $value)
    {
        if (headers_sent()) {
            return;
        }

        $allUserSettings = $this->getAllUserSettings();
        $allUserSettings[$name] = $value;
        $this->setAllUserSettings($allUserSettings);
    }

    /**
     * 删除当前用户某个设置
     *
     * @param $names
     * @return bool
     */
    public function deleteUserSetting($names)
    {
        if (headers_sent()) {
            return false;
        }

        $allUserSettings = $this->getAllUserSettings();
        $names = (array)$names;
        $deleted = false;

        foreach ($names as $name) {
            if (isset($allUserSettings[$name])) {
                unset($allUserSettings[$name]);
                $deleted = true;
            }
        }

        if ($deleted) {
            return $this->setAllUserSettings($allUserSettings);
        }

        return false;
    }

    /**
     * 删除当前用户所有设置
     */
    public function deleteAllUserSettings()
    {
        $user = Yii::$app->getUser();
        if ($user->getIsGuest()) {
            return;
        }

        $userId = $user->getId();
        $this->del('user.settings-' . $userId);
        Yii::$app->getResponse()->cookies[] = new Cookie([
            'name' => 'ycmf-settings-' . $userId,
            'value' => '',
            'expire' => 1,
            'path' => Yii::$app->getRequest()->getBaseUrl(),
        ]);
    }
}